import React, { useCallback, useContext, useMemo, useRef, useState } from 'react';
import { Button, Modal, Table, Form, Typography, Tooltip, message, Spin } from 'antd';
import { uniqueId, size, trim, omit, isEqual, zipObject, fill, defaults, last } from 'lodash';
import classNames from 'classnames';
import { useCustomCompareEffect } from 'react-use';

import BizIcon from '@/components/BizIcon';
import If from '@/components/If';
import Pre from '@/components/Pre';
import { defaultFormatResult, useDynamicList } from '@/hooks';

import { cpfService } from '@/services/salaryManage/salaryCalculateService';
import { BaseSettingContext } from '@/pages/SalaryManage/constant/BaseSettingContext';
import { NumberInput } from '@/pages/SalaryManage/components/NumberInput';
import { NumberSettingInput } from '@/pages/SalaryManage/components/NumberSettingInput';
import salaryStyle from '@/pages/SalaryManage/salaryManage.less';

import SignSelect, { LE, LT } from '../components/SignSelect';
import CPFContributionsModal from './CPFContributionsModal';
import util from './util';
import cpfSettingStyle from './index.less';

const TipItem = ({ messageArray, children }) => (
    <div className={cpfSettingStyle.tipItem}>
        <div className={cpfSettingStyle.content}>{children}</div>
        <div className={cpfSettingStyle.tip}>{messageArray.join(',')}</div>
    </div>
);

const tableColumns = ({
    onlyUpdate,
    onDelete,
    onEditEmployeeShare,
    onEditCompanyShare,
    handleRowUpdate,
    validateField
}) => {
    const rel = [
        {
            title: '雇员年龄',
            dataIndex: 'vvAgeRange',
            width: 330,
            render(text, record, index) {
                const errorFieldMap = record?.vvValidateInfo?.errorFieldMap || {};
                const messageArray = record?.vvValidateInfo?.tipMap?.vvAgeRange || [];

                return (
                    <TipItem messageArray={messageArray}>
                        <div className={cpfSettingStyle.rangeBox}>
                            <NumberInput
                                value={record.startAge}
                                onChange={value => handleRowUpdate('startAge', value, index, record)}
                                onBlur={util.delayExecute(() =>
                                    validateField(['startAge', 'endAge'], index, 'vvAgeRange')
                                )}
                                nonNegative
                                maxLength={3}
                                decimalPlaces={0}
                                placeholder="最小值"
                                className={classNames(cpfSettingStyle.start, {
                                    [cpfSettingStyle.error]: !!errorFieldMap?.startAge
                                })}
                            />

                            <SignSelect
                                value={record.startAgeSign}
                                onChange={value => handleRowUpdate('startAgeSign', value, index, record)}
                            />

                            <span>年龄</span>

                            <SignSelect
                                value={record.endAgeSign}
                                onChange={value => handleRowUpdate('endAgeSign', value, index, record)}
                            />

                            <NumberInput
                                value={record.endAge}
                                onChange={value => handleRowUpdate('endAge', value, index, record)}
                                onBlur={util.delayExecute(() =>
                                    validateField(['startAge', 'endAge'], index, 'vvAgeRange')
                                )}
                                nonNegative
                                maxLength={3}
                                decimalPlaces={0}
                                placeholder="最大值"
                                className={classNames(cpfSettingStyle.end, {
                                    [cpfSettingStyle.error]: !!errorFieldMap?.endAge
                                })}
                            />
                        </div>
                    </TipItem>
                );
            }
        },
        {
            title: '雇员该自然月薪资总额',
            dataIndex: 'vvTotalRange',
            width: 400,
            render(text, record, index) {
                const errorFieldMap = record?.vvValidateInfo?.errorFieldMap || {};
                const messageArray = record?.vvValidateInfo?.tipMap?.vvTotalRange || [];

                return (
                    <TipItem messageArray={messageArray}>
                        <div className={cpfSettingStyle.rangeBox}>
                            <NumberSettingInput
                                value={record.twStartAmt}
                                onChange={value => handleRowUpdate('twStartAmt', value, index, record)}
                                onBlur={util.delayExecute(() =>
                                    validateField(['twStartAmt', 'twEndAmt'], index, 'vvTotalRange')
                                )}
                                prefix="$"
                                placeholder="最小值"
                                align="left"
                                style={{ width: 100 }}
                                className={classNames(cpfSettingStyle.start, {
                                    [cpfSettingStyle.error]: !!errorFieldMap?.twStartAmt
                                })}
                            />

                            <SignSelect
                                value={record.twStartAmtSign}
                                onChange={value => handleRowUpdate('twStartAmtSign', value, index, 'vvTotalRange')}
                            />

                            <span>薪资总额</span>

                            <SignSelect
                                value={record.twEndAmtSign}
                                onChange={value => handleRowUpdate('twEndAmtSign', value, index, record)}
                            />

                            <NumberSettingInput
                                value={record.twEndAmt}
                                onChange={value => handleRowUpdate('twEndAmt', value, index, record)}
                                onBlur={util.delayExecute(() =>
                                    validateField(['twStartAmt', 'twEndAmt'], index, 'vvTotalRange')
                                )}
                                prefix="$"
                                placeholder="最大值"
                                align="left"
                                style={{ width: 100 }}
                                className={classNames(cpfSettingStyle.end, {
                                    [cpfSettingStyle.error]: !!errorFieldMap?.twEndAmt
                                })}
                            />
                        </div>
                    </TipItem>
                );
            }
        },
        {
            title: (
                <div>
                    总的公积金
                    <br />
                    缴交比例（雇员+雇主）
                </div>
            ),
            dataIndex: 'totalShare',
            width: 260,
            // align: 'center',
            render(text /* , record */) {
                return <Pre>{text || '系统自动合并结果'}</Pre>;
            },
            onCell(/* record, rowIndex */) {
                return {
                    style: {
                        background: '#FAFAFA',
                        cursor: 'not-allowed'
                    }
                };
            }
        },
        {
            title: (
                <div>
                    雇员公积金
                    <br />
                    缴交比例
                </div>
            ),
            dataIndex: 'employeeShare',
            width: 260,
            // align: 'center',
            render(text, record) {
                const messageArray = record?.vvValidateInfo?.tipMap?.employeeShare || [];

                return (
                    <TipItem messageArray={messageArray}>
                        <Pre>{text || <Typography.Text type="secondary">点击编辑</Typography.Text>}</Pre>
                    </TipItem>
                );
            },
            onCell(record, rowIndex) {
                return {
                    style: {
                        cursor: 'pointer'
                    },
                    onClick: () => {
                        onEditEmployeeShare(record, rowIndex);
                    }
                };
            }
        },
        {
            title: (
                <div>
                    雇主公积金
                    <br />
                    缴交比例
                </div>
            ),
            dataIndex: 'companyShare',
            width: 260,
            // align: 'center',
            render(text, record) {
                const messageArray = record?.vvValidateInfo?.tipMap?.companyShare || [];

                return (
                    <TipItem messageArray={messageArray}>
                        <Pre>{text || <Typography.Text type="secondary">点击编辑</Typography.Text>}</Pre>
                    </TipItem>
                );
            },
            onCell(record, rowIndex) {
                return {
                    style: {
                        cursor: 'pointer'
                    },
                    onClick: () => {
                        onEditCompanyShare(record, rowIndex);
                    }
                };
            }
        }
    ];

    if (!onlyUpdate) {
        rel.push({
            title: '操作',
            dataIndex: 'v_operate',
            fixed: 'right',
            width: 50,
            render(text, record, index) {
                return (
                    <Tooltip title="删除">
                        <Button
                            className={salaryStyle.operateIcon}
                            onClick={() => {
                                Modal.confirm({
                                    title: '确定删除',
                                    content: '确定要删除吗',
                                    okText: '确定',
                                    cancelText: '取消',
                                    onOk() {
                                        onDelete(record, index);
                                    }
                                });
                            }}
                        >
                            <BizIcon type="DeleteIcon" />
                        </Button>
                    </Tooltip>
                );
            }
        });
    }
    return rel;
};

const validateRow = (row, validateFields) => {
    const tipMap = {};
    const errorFieldMap = {};

    const addMessageTip = (warnField, warnMessage) => {
        if (!tipMap[warnField]) {
            tipMap[warnField] = [];
        }
        tipMap[warnField].push(warnMessage);
    };

    // 1. 单个字段校验
    // <editor-fold desc="单个字段校验">
    if (util.needValidate('employeeShare', validateFields) && size(row.employeeShareDetails) === 0) {
        addMessageTip('employeeShare', '请编辑!');
    }

    if (util.needValidate('companyShare', validateFields) && size(row.companyShareDetails) === 0) {
        addMessageTip('companyShare', '请编辑!');
    }
    // </editor-fold>

    // 2.多个字段连合校验
    // <editor-fold desc="多个字段连合校验">
    if (util.needValidate(['startAge', 'endAge'], validateFields) && !trim(row.startAge) && !trim(row.endAge)) {
        errorFieldMap.startAge = true;
        errorFieldMap.endAge = true;
        addMessageTip('vvAgeRange', '雇员年龄起始值与结束值至少填一个!');
    }

    if (
        util.needValidate(['startAge', 'endAge'], validateFields) &&
        trim(row.startAge) &&
        trim(row.endAge) &&
        row.startAge > row.endAge
    ) {
        errorFieldMap.startAge = true;
        errorFieldMap.endAge = true;
        addMessageTip('vvAgeRange', '雇员年龄起始值不能大于结束值!');
    }

    if (util.needValidate(['twStartAmt', 'twEndAmt'], validateFields) && !trim(row.twStartAmt) && !trim(row.twEndAmt)) {
        errorFieldMap.twStartAmt = true;
        errorFieldMap.twEndAmt = true;
        addMessageTip('vvTotalRange', '雇员该自然月薪资总额起始值与结束值至少填一个!');
    }

    if (
        util.needValidate(['twStartAmt', 'twEndAmt'], validateFields) &&
        trim(row.twStartAmt) &&
        trim(row.twEndAmt) &&
        row.twStartAmt > row.twEndAmt
    ) {
        errorFieldMap.twStartAmt = true;
        errorFieldMap.twEndAmt = true;
        addMessageTip('vvTotalRange', '雇员该自然月薪资总额起始值不能大于结束值!');
    }
    // </editor-fold>

    return { tipMap, errorFieldMap };
};

/**
 * 添加校验信息
 * @param {Array | Object} rows
 * @param {Array | Object } validateFields
 * @returns {(*&{validateInfo: {errorField, message}})|*}
 */
const addValidateInfo = (rows, validateFields) =>
    util.mapRows(rows, row => ({ vvValidateInfo: validateRow(row, validateFields) }));

const EMPLOYEE_SHARE_TYPE = 1;
const COMPANY_SHARE_TYPE = 2;

const DetailModal = ({ cpfModel, cpfDetailId, title, visible, onCancel, onOk, onlyUpdate }) => {
    const {
        baseSetting: { scale = 2 }
    } = useContext(BaseSettingContext);

    const [loading, setLoading] = useState(false);
    const { list: dataSource, resetList: resetDataSource, push, replace, remove } = useDynamicList([]);
    const [contributionsModalVisible, setContributionsModalVisible] = useState(false);
    const [shareType, setShareType] = useState(null);
    const [shareModel, setShareModel] = useState({});
    const operateRef = useRef({ index: null, record: null });

    const onAdd = () => {
        const newItem = {
            vv_id: uniqueId('id'),
            startAge: null,
            startAgeSign: LT.value,
            endAge: null,
            endAgeSign: LE.value,
            twStartAmt: null,
            twStartAmtSign: LT.value,
            twEndAmt: null,
            twEndAmtSign: LE.value,
            employeeShareDetails: null,
            companyShareDetails: null
        };

        if (size(dataSource) === 0) {
            push(newItem);
            return;
        }
        // 取出最后一条数据
        const { startAge, startAgeSign, endAge, endAgeSign, twEndAmt, twEndAmtSign } = last(dataSource);

        // 用一条数据的年龄范围
        Object.assign(newItem, {
            startAge,
            startAgeSign,
            endAge,
            endAgeSign
        });

        if (trim(twEndAmt)) {
            Object.assign(newItem, { twStartAmt: twEndAmt, twEndAmt: null });

            Object.assign(newItem, {
                twStartAmtSign: LT.value === twEndAmtSign ? LE.value : LT.value,
                twEndAmtSign
            });
        }

        push(newItem);
    };

    const onDelete = useCallback(
        (record, index) => {
            remove(index);
        },
        [remove]
    );

    const onEditEmployeeShare = useCallback((record, index) => {
        operateRef.current = { index, record };
        setContributionsModalVisible(true);
        setShareType(EMPLOYEE_SHARE_TYPE);
        setShareModel(record?.employeeShareDetails || [{}]);
    }, []);

    const handleRowUpdate = useCallback(
        (field, fieldValue, index) => {
            const newRecord = { ...dataSource[index], [field]: fieldValue };
            replace(index, newRecord);
        },
        [dataSource, replace]
    );

    const validateField = useCallback(
        (fields, index, tipRangeField, row) => {
            const record = row || dataSource[index];
            const oldValidateInfo = record.vvValidateInfo || { tipMap: {}, errorFieldMap: {} };
            const defaultValidateInfo = {
                errorFieldMap: zipObject(fields, fill(Array(fields), false)),
                tipMap: tipRangeField ? { [tipRangeField]: [] } : zipObject(fields, fill(Array(fields), []))
            };
            const validateInfo = validateRow(record, fields);
            const newValidateInfo = {
                errorFieldMap: defaults(validateInfo.errorFieldMap, defaultValidateInfo.errorFieldMap),
                tipMap: defaults(validateInfo.tipMap, defaultValidateInfo.tipMap)
            };
            const mergeValidateInfo = {
                tipMap: { ...oldValidateInfo.tipMap, ...newValidateInfo.tipMap },
                errorFieldMap: { ...oldValidateInfo.errorFieldMap, ...newValidateInfo.errorFieldMap }
            };
            const newRecord = { ...record, vvValidateInfo: mergeValidateInfo };
            replace(index, newRecord);
        },
        [dataSource, replace]
    );

    const onEditCompanyShare = useCallback((record, index) => {
        operateRef.current = { index, record };
        setContributionsModalVisible(true);
        setShareType(COMPANY_SHARE_TYPE);
        setShareModel(record?.companyShareDetails || [{}]);
    }, []);

    const handleOk = () => {
        const newDataSource = addValidateInfo(dataSource);
        resetDataSource(newDataSource);

        if (size(newDataSource) === 0) {
            message.error('请添加数据');
            return;
        }

        const hasError = data => size(Object.keys((data.vvValidateInfo || { tipMap: {} }).tipMap || {})) > 0;
        // 如果校验不通过
        if (newDataSource.find(data => hasError(data))) {
            message.error('请正确填写信息');
            return;
        }

        const postData = newDataSource.map(item => ({
            cpfId: cpfModel.id,
            ...omit(item, ['vvId', 'vvValidateInfo', 'vvShowMax'])
        }));

        const savePromise = onlyUpdate ? cpfService.updateCpfDetail(postData[0]) : cpfService.batchSaveDetail(postData);

        savePromise.then(defaultFormatResult.formatResult).then(response => {
            if (response) {
                message.success('保存成功！');
                onOk(response);
            }
        });
    };

    /**
     *
     * @param {Array} newShareModel
     */
    const handleContributionsModalOk = newShareModel => {
        const mergeModel = newShareModel.map(item => ({
            // 1：百分比% 2：小数
            showStyle: 1,
            cpfShareType: shareType,
            ...item
        }));

        const newRecord = { ...operateRef.current.record };

        if (shareType === COMPANY_SHARE_TYPE) {
            Object.assign(newRecord, {
                companyShare: util.getFormulaDescription(mergeModel, scale),
                companyShareDetails: mergeModel
            });
        }

        if (shareType === EMPLOYEE_SHARE_TYPE) {
            Object.assign(newRecord, {
                employeeShare: util.getFormulaDescription(mergeModel, scale),
                employeeShareDetails: mergeModel
            });
        }

        // 合计缴交比例
        Object.assign(newRecord, {
            totalShare: util.getFormulaDescription(
                [].concat(newRecord.employeeShareDetails || []).concat(newRecord.companyShareDetails || []),
                scale
            )
        });

        const { index } = operateRef.current;
        // 替换数据
        replace(index, newRecord);
        util.delayExecute(() => {
            validateField(
                shareType === EMPLOYEE_SHARE_TYPE ? ['employeeShare'] : ['companyShare'],
                index,
                null,
                newRecord
            );
        })();
        // 关掉弹框
        setContributionsModalVisible(false);
    };

    const columns = useMemo(
        () =>
            tableColumns({
                onlyUpdate,
                onDelete,
                onEditEmployeeShare,
                onEditCompanyShare,
                validateField,
                handleRowUpdate
            }),
        [handleRowUpdate, onDelete, onEditCompanyShare, onEditEmployeeShare, onlyUpdate, validateField]
    );

    useCustomCompareEffect(
        () => {
            if (cpfDetailId) {
                setLoading(true);
                cpfService
                    .getCpfDetail({ id: cpfDetailId })
                    .then(defaultFormatResult.formatResult)
                    .then(data => {
                        if (data) {
                            resetDataSource([{ vvId: uniqueId('id'), ...data }]);
                        }
                    })
                    .finally(() => setLoading(false));
            } else {
                onAdd();
            }
        },
        [cpfDetailId, resetDataSource],
        ([, ...prevCpfDetailId], [, ...nextCpfDetailId]) => isEqual(prevCpfDetailId, nextCpfDetailId)
    );

    return (
        <>
            <Modal
                title={title}
                visible={visible}
                width="calc(100vw - 200px)"
                onCancel={onCancel}
                onOk={handleOk}
                style={{ maxWidth: '1412px', top: 50 }}
                bodyStyle={{ maxHeight: 'calc(100vh - 200px)', overflow: 'auto' }}
            >
                <Spin spinning={loading}>
                    <Form layout="inline" className={cpfSettingStyle.detailModal}>
                        <Form.Item label={<span className={salaryStyle.labelSecondary}>表格类型</span>}>
                            {cpfModel.prName}
                        </Form.Item>
                        <Table
                            rowKey="vvId"
                            columns={columns}
                            dataSource={dataSource}
                            pagination={false}
                            scroll={{ x: 'max-content' }}
                            bordered
                            className={cpfSettingStyle.detailTable}
                        />

                        <If condition={!onlyUpdate}>
                            <Button type="dashed" block onClick={onAdd} style={{ marginTop: 16, marginBottom: 32 }}>
                                + 添加
                            </Button>
                        </If>
                    </Form>
                </Spin>
            </Modal>
            <If condition={contributionsModalVisible}>
                <CPFContributionsModal
                    visible={contributionsModalVisible}
                    title={shareType === COMPANY_SHARE_TYPE ? '雇主公积金缴交比例' : '雇员公积金缴交比例'}
                    model={shareModel}
                    onCancel={() => setContributionsModalVisible(false)}
                    onOk={handleContributionsModalOk}
                />
            </If>
        </>
    );
};
DetailModal.defaultProps = {
    cpfModel: {},
    title: '新增',
    onCancel: () => {},
    onOk: () => {},
    onlyUpdate: false
};

export default DetailModal;
